/*
 * ServerSync.java
 *
 * Created on 2 de Maio de 2007, 16:11
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package net.onmotion;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Vector;

import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;

import net.onmotion.network.GetHttpData;
import net.onmotion.network.HttpData;
import net.onmotion.network.MultipartHttpData;
import net.onmotion.network.NetworkManager;
import net.onmotion.util.Log;
import net.onmotion.util.StringTokenizer;
import net.onmotion.util.Float;

/**
 * 
 * @author sestevao
 */
public class LocationManager implements Runnable {

  public static final String server = "http://www.onmotion.net/";
  //public static final String server = "http://127.0.0.1/onmotion/";

  public boolean active = true;

  public Vector locations;

  int currentPos = 0;

  Thread serverThread;

  StringBuffer sb;

  HttpData httpData;

  MultipartHttpData multipartHttpData;

  /** Creates a new instance of ServerSync */
  public LocationManager() {
    locations = new Vector(10);
  }

  public void start() {
    serverThread = new Thread(this);
    serverThread.start();
  }

  public void stop() {
    try {
      if (active) {
        active = false;
        serverThread.join();
      }
    } catch (InterruptedException ex) {
      Log.log("LocationManager",ex);
      active = false;
    }
  }

  public boolean isValidUser() {    
     return OnMotionMidlet.networkActive;
  }

  public void run() {
    try {
      active = true;
      while (active) {
        // check if valid user
        if (isValidUser()) {
          if (locations.size() > currentPos) {            
            Location currentLocation = (Location) locations
                .elementAt(currentPos);
            // check if already on the server
            if (currentLocation.id == -1) {
              if (sendData(currentLocation)) {
                currentPos++;
              }
            } else {
              currentPos++;
            }
          }
        }
        Thread.sleep(1000);
      }
    } catch (Throwable t) {
      Log.log(t);
    }
  }

  public void addLocation(Location location) {
    if (location != null) {      
      locations.addElement(location);
    } else {
      Log.log("addLocation: locations is null");
    }
  }

  public boolean geoCodeLocation(Location location) {
    final String API_KEY="ABQIAAAA6cs7716kYs3Ko1SvfMt_exQXdHDrzlCyUW1cOQLk9qowMRLGdxT4IMJUue67Jy2jbNedZmC-wzC96g";
    final String server="http://maps.google.com/maps/geo";
    GetHttpData httpData = new GetHttpData();
                 
    httpData.addPart("output", "csv");
    httpData.addPart("q", location.place);
    httpData.addPart("key", API_KEY);    
    // send request to server
    byte result[]= NetworkManager.sendReceive(server, httpData);
    if (result != null) {      
      String answer = new String(result);
      Log.log(answer);
      StringTokenizer st = new StringTokenizer(answer,",");      
      if ( answer.startsWith("200")) {
        Log.log(st.nextToken()); // status        
        String accuracy = st.nextToken();
        Log.log(accuracy);
        String lat = st.nextToken();
        Log.log(lat);
        String lng = st.nextToken();
        
        location.setLatitude(lat);
        location.setLongitude(lng);
        location.valid = true;
      }
    }
    return false;
  }
  
  public boolean sendData(Location location) {
    if (location == null) {
      Log.log("sendData: location is null");
      return false;
    }
    if (httpData == null) {
      httpData = new HttpData();
    } else {
      httpData.clear();
    }
    /*
    if (!location.isValid()){    
      return geoCodeLocation(location);
    }
    */    
    httpData.addPart("lat", location.getLatitude());
    httpData.addPart("lng", location.getLongitude());
    httpData.addPart("altitude", location.getAltitude());
    httpData.addPart("name", location.name);
    httpData.addPart("comment", location.description);
    httpData.addPart("time", location.getTimeStampNetwork());
    httpData.addPart("track", location.track + "");
    httpData.addPart("userLogin", OnMotionMidlet.user);
    httpData.addPart("userTid", OnMotionMidlet.userTrackId);
    httpData.addPart("type", location.type+"");

    byte[] result = NetworkManager.sendReceive(server + "savePoint.php",
        httpData);
    String sResult = new String(result);
    if (result != null) {
      Log.log("Save Point result:" + sResult);
      int newId = 1;
      try {
        StringTokenizer st = new StringTokenizer(sResult,",");
        newId = Integer.parseInt(st.nextToken());
        // Check if point saved
        if (newId != -1) {
          location.id = newId;
          if ( st.hasMoreTokens()){
            location.track = Integer.parseInt(st.nextToken());
          }
          // Check if image available
          if (location.photo != null) {
            if (multipartHttpData == null) {
              multipartHttpData = new MultipartHttpData();
            } else {
              multipartHttpData.clear();
            }
            // prepare post request to send image
            multipartHttpData.addPart("userLogin", OnMotionMidlet.user);
            multipartHttpData.addPart("userTid", OnMotionMidlet.userTrackId);
            multipartHttpData.addPart("id", Integer.toString(location.id));
            multipartHttpData.addPart("file", location.photo, "image/png",
                "file.png");
            multipartHttpData.addPart();
            Log.log("Send Image to Server");
            // send Image to server
            result = NetworkManager.sendReceive(server + "saveImage.php",
                multipartHttpData);
            Log.log("Send Image result:" + new String(result));
            return true;
          }
          return true;
        }
      } catch (Exception nfe) {
        Log.log("Convert error",nfe);
      }      
    }
    return false;
  }

  public void saveData() {
    try {
      RecordStore options = RecordStore.openRecordStore("landmarks", true);
      byte[] data = saveLocations();
      if (options.getNumRecords() != 0) // record store not empty
      {
        options.setRecord(1, data, 0, data.length);
      } else {
        options.addRecord(data, 0, data.length);
      }
      options.closeRecordStore();
    } catch (RecordStoreException ex) {
      Log.log(ex);
    }
  }

  public void loadData() {
    try {
      RecordStore options = RecordStore.openRecordStore("landmarks", true);
      if (options.getNumRecords() != 0) // record store not empty
      {
        loadLocations(options.getRecord(1));
      }
      options.closeRecordStore();
    } catch (RecordStoreException ex) {
      Log.log(ex);
    }
  }

  public byte[] saveLocations() {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    DataOutputStream dos = new DataOutputStream(baos);
    int size = 0;
    if (locations != null) {
      size = locations.size();
    }
    try {
      dos.writeInt(size);
      for (int i = 0; i < size; i++) {
        Location location = (Location) locations.elementAt(i);
        dos.writeInt(location.id);
        dos.writeLong(location.timestamp.getTime());
        dos.writeUTF(location.lat.toString());        
        dos.writeUTF(location.lng.toString());        
        dos.writeUTF(location.alt.toString());
        dos.writeUTF(location.name);
        dos.writeUTF(location.description);
        dos.write(location.track);
        if (location.photo != null) {
          dos.writeInt(location.photo.length);
          dos.write(location.photo);
        } else {
          dos.writeInt(0);
        }
      }
    } catch (IOException ex) {
      Log.log(ex);
    }

    return baos.toByteArray();
  }

  public void loadLocations(byte[] data) {
    ByteArrayInputStream bais = new ByteArrayInputStream(data);
    DataInputStream dis = new DataInputStream(bais);
    try {
      int size = dis.readInt() + 1;
      locations = new Vector(size);
      for (int i = 0; i < size -1; i++) {
        Location location = new Location();
        location.id = dis.readInt();
        location.timestamp.setTime(dis.readLong());
        location.lat = Float.parse(dis.readUTF(),10);        
        location.lng = Float.parse(dis.readUTF(),10);        
        location.alt = Float.parse(dis.readUTF(),10);
        location.name = dis.readUTF();
        location.description = dis.readUTF();
        location.track = dis.read();
        int photoSize = dis.readInt();
        if (photoSize == 0) {
          location.photo = null;
        } else {
          location.photo = new byte[photoSize];
          dis.read(location.photo, 0, location.photo.length);
        }
        locations.addElement(location);
      }
      dis.close();
    } catch (IOException ex) {
      Log.log(ex);
    }

  }

}
